﻿/************************************************************************

 This file is part of "10 Second Tim".

 "10 Second Tim" is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 "10 Second Tim" is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with "10 Second Tim".  If not, see <http://www.gnu.org/licenses/>.

************************************************************************/

// All code (c)2013 Scott Bevin. all rights reserved

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace LDE.Input
{
	public class KeyboardInputDevice : IInputDevice
	{
		#region Members

		private int m_slotIdx;

		private static int s_deviceTypeId = ( "Keyboard" ).GetHashCode( );

		public static int DeviceTypeId { get { return s_deviceTypeId; } }

		public class KeyboardButton : InputButton
		{
			public Keys Key = Keys.A;
		}

		private List<KeyboardButton> m_keys = new List<KeyboardButton>( );

		private InputTrigger m_stickUpInputTrigger = new InputTrigger( "Stick Up" ).Add( Keys.W ).Add( Keys.Up );
		private InputTrigger m_stickDownInputTrigger = new InputTrigger( "Stick Down" ).Add( Keys.S ).Add( Keys.Down );
		private InputTrigger m_stickLeftInputTrigger = new InputTrigger( "Stick Left" ).Add( Keys.A ).Add( Keys.Left );
		private InputTrigger m_stickRightInputTrigger = new InputTrigger( "Stick Right" ).Add( Keys.D ).Add( Keys.Right );

		#endregion Members

		public KeyboardInputDevice( int slotIdx )
		{
			m_slotIdx = slotIdx;

			foreach ( Keys key in Enum.GetValues( typeof( Keys ) ) )
			{
				KeyboardButton nk = new KeyboardButton( );
				nk.Key = key;
				m_keys.Add( nk );
			}
		}

		public int GetDeviceTypeId( )
		{
			return s_deviceTypeId;
		}

		public int GetDeviceId( )
		{
			return m_slotIdx;
		}

		public InputButton IsPressed( InputTrigger trigger )
		{
			foreach ( Keys k in trigger.KeyboardButtons )
			{
				foreach ( KeyboardButton key in m_keys )
				{
					if ( key.Key == k )
					{
						if ( key.Down && !key.DownLF )
							return key;
					}
				}
			}

			return null;
		}

		public InputButton IsHeld( InputTrigger trigger )
		{
			foreach ( Keys k in trigger.KeyboardButtons )
			{
				foreach ( KeyboardButton key in m_keys )
				{
					if ( key.Key == k )
					{
						if ( key.Down && key.CurrStateTimer >= InputManager.Holdtime )
							return key;
					}
				}
			}

			return null;
		}

		public InputButton IsDown( InputTrigger trigger )
		{
			foreach ( Keys k in trigger.KeyboardButtons )
			{
				foreach ( KeyboardButton key in m_keys )
				{
					if ( key.Key == k )
					{
						if ( key.Down )
							return key;
					}
				}
			}

			return null;
		}

		public InputButton IsReleased( InputTrigger trigger )
		{
			foreach ( Keys k in trigger.KeyboardButtons )
			{
				foreach ( KeyboardButton key in m_keys )
				{
					if ( key.Key == k )
					{
						if ( !key.Down && key.DownLF )
							return key;
					}
				}
			}

			return null;
		}

		public InputButton IsTapped( InputTrigger trigger )
		{
			foreach ( Keys k in trigger.KeyboardButtons )
			{
				foreach ( KeyboardButton key in m_keys )
				{
					if ( key.Key == k )
					{
						if ( !key.Down && key.DownLF && key.PrevStateTimer < InputManager.TapTime )
							return key;
					}
				}
			}

			return null;
		}

		public void UpdateState( float dt )
		{
#if SILVERLIGHT
			KeyboardState state = Keyboard.GetState(  );
#else
			KeyboardState state = Keyboard.GetState( (PlayerIndex)m_slotIdx );
#endif

			for ( int i = 0; i < m_keys.Count; ++i )
			{
				KeyboardButton key = m_keys[ i ];

				key.DownLF = key.Down;
				key.Down = state.IsKeyDown( key.Key );

				if ( key.Down != key.DownLF )
				{
					key.PrevStateTimer = key.CurrStateTimer;
					key.CurrStateTimer = 0.0f;
				}

				key.CurrStateTimer += dt;
			}
		}

		public bool IsConnected( )
		{
			// Todo... work this one out (keyboards connected to xbox controllers)
			return true;
		}

		public Microsoft.Xna.Framework.Vector2 GetStickVals( )
		{
			Vector2 retVal = Vector2.Zero;

			if ( IsDown( m_stickLeftInputTrigger ) != null )
				retVal.X = -1.0f;
			if ( IsDown( m_stickRightInputTrigger ) != null )
				retVal.X = 1.0f;

			if ( IsDown( m_stickUpInputTrigger ) != null )
				retVal.Y = 1.0f;
			if ( IsDown( m_stickDownInputTrigger ) != null )
				retVal.Y = -1.0f;

			return retVal;
		}

		public bool IsPointingDevice( )
		{
			return false;
		}

		public Point GetPointerPos( )
		{
			return Point.Zero;
		}
	}
}